package com.lf.data;

import org.apache.log4j.Logger;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by 严秋旺 on 2015/1/11.
 */
public class Form {

    private static final Logger LOGGER = Logger.getLogger(Form.class);

    private HttpServletRequest request;

    public Form(HttpServletRequest request) {
        this.request = request;
    }

    public int getInteger(String param) {
        return getInteger(param, 0);
    }

    public int getInteger(String param, int defval) {
        String value = request.getParameter(param);
        int val = defval;
        if (value != null) {
            try {
                val = Integer.parseInt(value);
            } catch (Exception e) {
                val = defval;
                LOGGER.warn("参数转换整型异常：" + e.getMessage());
            }
        }
        return val;
    }

    public String getString(String param) {
        return getString(param, "");
    }

    public String getString(String param, String defval) {
        String value = request.getParameter(param);
        if (value == null) {
            value = defval;
        }
        return value;
    }

    public String[] getStrings(String param) {
        return request.getParameterValues(param);
    }

    public List getList(String param) {
        String[] values = request.getParameterValues(param);
        List<String> val = new ArrayList<>();
        for (String v : values) {
            val.add(v);
        }
        return val;
    }

    public boolean getCluster(Cluster cluster) {
        return getCluster(cluster, true, false);
    }

    public boolean getCluster(Cluster cluster, boolean format, boolean acceptWrong) {
        return getCluster(cluster, format, acceptWrong, null);
    }

    /**
     * 从表单接收数据簇
     *
     * @param cluster     待接收数据簇对象
     * @param format      是否进行值转换
     * @param acceptWrong 是否接收错误值
     * @param node        节点
     * @return 当所有值验证通过则返回true，否则false
     */
    public boolean getCluster(Cluster cluster, boolean format, boolean acceptWrong, String node) {
        boolean result = true;
        if (node == null) {
            node = "";
        } else {
            node = node + '.';
        }
        Field[] keys = cluster.getClass().getFields();
        for (Field key : keys) {
            Key annotation = key.getAnnotation(Key.class);
            if (annotation == null) {
                continue;
            }
            String keyPath = null;
            try {
                keyPath = key.get(cluster).toString();
            } catch (IllegalAccessException e) {
                LOGGER.error("获取键名异常(" + key.getName() + ")：" + e);
                continue;
            }
            String param = request.getParameter(node + keyPath);
            if (param == null) {
                if (!annotation.nullable()) {
                    result = false;
                }
                continue;
            }
            boolean checkResult = Validate.check(annotation.check(), param);
            result = checkResult ? result : false;
            if (checkResult || (!checkResult && acceptWrong)) {
                Object value = null;
                if (format) {
                    try {
                        value = annotation.valueType().parseValue(param);
                    } catch (Exception e) {
                        LOGGER.warn("值转换失败(" + param + ")：" + e);
                    }
                } else {
                    value = param;
                }
                ClusterUtil.put(cluster, keyPath, annotation.keyType(), value);
            }
        }
        return result;
    }

    public boolean getBean(Object bean) {
        return getBean(bean, false);
    }

    public boolean getBean(Object bean, boolean acceptWrong) {
        return getBean(bean, acceptWrong, null);
    }

    /**
     * 从表单接收对象
     *
     * @param bean        待接收对象
     * @param acceptWrong 是否接收错误值
     * @param node        节点
     * @return 属性值验证结果，全部通过则返回true，否则返回false
     */
    public boolean getBean(Object bean, boolean acceptWrong, String node) {
        boolean result = true;
        if (node == null) {
            node = "";
        } else {
            node = node + '.';
        }
        Class beanClass = bean.getClass();
        Field[] properties = beanClass.getDeclaredFields();
        for (Field property : properties) {
            Key annotation = property.getAnnotation(Key.class);
            if (annotation == null) {
                continue;
            }
            String param = request.getParameter(node + property.getName());
            if (param == null) {
                if (!annotation.nullable()) {
                    result = false;
                }
                continue;
            }
            boolean checkResult = Validate.check(annotation.check(), param);
            result = checkResult ? result : false;
            if (checkResult || (!checkResult && acceptWrong)) {
                Object value = null;
                try {
                    value = annotation.valueType().parseValue(param);
                    String propertyName = property.getName();
                    String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
                    Method method = beanClass.getMethod(methodName, value.getClass());
                    method.invoke(bean, value);
                } catch (Exception e) {
                    LOGGER.error("属性赋值异常[" + property + "](" + param + ")：" + e);
                }
            }
        }
        return result;
    }
}
